
#ifndef ACCTFIELDS_H
#define ACCTFIELDS_H

class AccountField
{
public:
	enum ProtocolVersions { PROTOVERSION_V1 = 0x01 };

	AccountField();

	bool8	validate(const String& text) const;
	uint32	serialize(enum ProtocolVersions, uint8* pRawTo) const;
	uint32	deserialize(uint8* pRawFrom);

	int32 minLength;
	int32 maxLength;
	bool8 numbersOnly;
	bool8 required;
	bool8 allowQuotes;
	bool8 allowSpaces;
	bool8 dropDown;
};

class AcctCreateFields
{
public:
	enum ProtocolVersions { PROTOVERSION_V1 = 0x01 };

	uint32	serialize(enum ProtocolVersions, uint8* pRawTo) const;
	uint32	deserialize(uint8* pRawFrom);

	AccountField Login;
	AccountField Password;
	AccountField FirstName;
	AccountField LastName;
	AccountField AddressLine1;
	AccountField AddressLine2;
	AccountField City;
	AccountField State;
	AccountField Zip;
	AccountField DaytimePhone;
	AccountField EveningPhone;
	AccountField EMailAddress;
	AccountField Birthdate;
	AccountField Country;

	// [AO 2008-01-18] For lazy initialization
	AcctCreateFields(): initialized(false) {}
	bool initialized;
};

class AcctLoginFields
{
public:
	enum ProtocolVersions { PROTOVERSION_V1 = 0x01 };

	uint32	serialize(enum ProtocolVersions, uint8* pRawTo) const;
	uint32	deserialize(uint8* pRawFrom);

	AccountField Login;
	AccountField Password;

	// [AO 2008-01-18] For lazy initialization
	AcctLoginFields(): initialized(false) {}
	bool initialized;
};

inline
AccountField::AccountField()
{
	minLength = 0;
	maxLength = -1;
	numbersOnly = false;
	required = true;
	allowQuotes = false;
	allowSpaces = true;
	dropDown = false;
}

inline
bool8 
AccountField::validate(const String& text) const
{
	if (required)
	{
		if (dropDown)
		{
			if (!text.getLength())
				return false;
		}
		else
		{
			if ((int32)text.getLength() < minLength || (int32)text.getLength() > maxLength)
				return false;

			if (numbersOnly)
			{
				for(uint32 i=0;i<text.getLength();i++)
				{
					if (text[i] < '0' || text[i] > '9')
						return false;
				}
			}
			else
			{
				if (!allowQuotes)
				{
					if (text.find("\'") != String::NPOS || 
						text.find("\"") != String::NPOS)
						return false;
				}

				if (!allowSpaces)
				{
					if (text.find(" ") != String::NPOS)
						return false;
				}
			}
		}
	}

	return true;
}

inline
uint32
AccountField::serialize(enum ProtocolVersions ver, uint8* pRawTo) const
{
	uint32 i = 0;

	pRawTo[i++] = PROTOVERSION_V1;

	pRawTo[i++] = (uint8)(((minLength) & 0xff));
	pRawTo[i++] = (uint8)((((minLength) >> 8) & 0xff));
	pRawTo[i++] = (uint8)((((minLength) >> 16) & 0xff));
	pRawTo[i++] = (uint8)((((minLength) >> 24) & 0xff));

	pRawTo[i++] = (uint8)(((maxLength) & 0xff));
	pRawTo[i++] = (uint8)((((maxLength) >> 8) & 0xff));
	pRawTo[i++] = (uint8)((((maxLength) >> 16) & 0xff));
	pRawTo[i++] = (uint8)((((maxLength) >> 24) & 0xff));

	pRawTo[i++] = numbersOnly;
	pRawTo[i++] = required;
	pRawTo[i++] = allowQuotes;
	pRawTo[i++] = allowSpaces;
	pRawTo[i++] = dropDown;

	return i;
}

inline
uint32
AccountField::deserialize(uint8* pRawFrom)
{
	uint32 i = 0;

	if (pRawFrom[i++] == PROTOVERSION_V1)
	{
		minLength =	((pRawFrom[i+0] <<  0) | (pRawFrom[i+1] <<  8) |
			(pRawFrom[i+2] << 16) | pRawFrom[i+3] << 24);
		i += 4;

		maxLength =	((pRawFrom[i+0] <<  0) | (pRawFrom[i+1] <<  8) |
			(pRawFrom[i+2] << 16) | pRawFrom[i+3] << 24);
		i += 4;

		numbersOnly = pRawFrom[i++];
		required = pRawFrom[i++];
		allowQuotes = pRawFrom[i++];
		allowSpaces = pRawFrom[i++];
		dropDown = pRawFrom[i++];
	}

	return i;
}

inline 
uint32
AcctCreateFields::serialize(enum ProtocolVersions ver, uint8* pRawTo) const
{
	uint32 i = 0;

	pRawTo[i++] = PROTOVERSION_V1;

	i += Login.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += Password.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += FirstName.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += LastName.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += AddressLine1.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += AddressLine2.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += City.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += State.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += Zip.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += DaytimePhone.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += EveningPhone.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += EMailAddress.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += Birthdate.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += Country.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );

	return i;
}


inline 
uint32
AcctCreateFields::deserialize(uint8* pRawFrom)
{
	uint32 i = 0;

	if (pRawFrom[i++] == PROTOVERSION_V1)
	{
		i += Login.deserialize( pRawFrom + i );
		i += Password.deserialize( pRawFrom + i );
		i += FirstName.deserialize( pRawFrom + i );
		i += LastName.deserialize( pRawFrom + i );
		i += AddressLine1.deserialize( pRawFrom + i );
		i += AddressLine2.deserialize( pRawFrom + i );
		i += City.deserialize( pRawFrom + i );
		i += State.deserialize( pRawFrom + i );
		i += Zip.deserialize( pRawFrom + i );
		i += DaytimePhone.deserialize( pRawFrom + i );
		i += EveningPhone.deserialize( pRawFrom + i );
		i += EMailAddress.deserialize( pRawFrom + i );
		i += Birthdate.deserialize( pRawFrom + i );
		i += Country.deserialize( pRawFrom + i );
	}

	return i;
}

inline 
uint32
AcctLoginFields::serialize(enum ProtocolVersions ver, uint8* pRawTo) const
{
	uint32 i = 0;

	pRawTo[i++] = PROTOVERSION_V1;

	i += Login.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );
	i += Password.serialize( AccountField::PROTOVERSION_V1, pRawTo + i );

	return i;
}

inline 
uint32
AcctLoginFields::deserialize(uint8* pRawFrom)
{
	uint32 i = 0;

	if (pRawFrom[i++] == PROTOVERSION_V1)
	{
		i += Login.deserialize( pRawFrom + i );
		i += Password.deserialize( pRawFrom + i );
	}

	return i;
}

#endif